Imports System.Collections.Generic
Imports System.IO
Imports System.Text
Imports System.Text.RegularExpressions
Imports System.Xml
Imports System.Xml.Schema
Imports System.Xml.XPath

Public Class Dtd
    Inherits XmlResolver

    Private Shared ReadOnly DTD_FOLDER_PATH As String = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dtd")

    Public Shared Function Preview(ByVal name As String, ByVal publicId As String, ByVal systemId As String, ByVal subset As String) As String

        Dim sb As New StringBuilder()

        Dim settings As New XmlWriterSettings()
        settings.OmitXmlDeclaration = True

        Using tw As New StringWriter(sb)
            Dim xw As XmlWriter = XmlWriter.Create(tw, settings)
            xw.WriteDocType(name, publicId, systemId, subset)
            xw.Close()
        End Using

        Return sb.ToString()

    End Function

    Private ReadOnly _Subset As String
    Private ReadOnly _Name As String
    Private ReadOnly _Buffer() As Byte

    'Private ReadOnly _PubId As String
    'Private ReadOnly _SysId As String

    'Public Sub New(ByVal docType As String)

    'End Sub

    'Public ReadOnly Property Name() As String
    '    Get
    '        Return _Name
    '    End Get
    'End Property

    'Public ReadOnly Property PubId() As String
    '    Get
    '        Return _PubId
    '    End Get
    'End Property

    'Public ReadOnly Property SysId() As String
    '    Get
    '        Return _SysId
    '    End Get
    'End Property

    'Public ReadOnly Property Subset() As String
    '    Get
    '        Return _Subset
    '    End Get
    'End Property

    Public Sub New(ByVal filename As String, ByVal name As String)

        Dim uri As String = Path.Combine(DTD_FOLDER_PATH, filename)

        Using sr As New StreamReader(uri)
            _Subset = sr.ReadToEnd()
            'sr.Close()
        End Using

        _Name = name

        _Buffer = Encoding.ASCII.GetBytes(_Subset)

    End Sub

    Public Overrides Function ToString() As String

        Static str As String = "<!DOCTYPE " & _Name & "[" & _Subset & "]>"

        Return str

    End Function

    'Public Sub Validate(ByVal xmlWithoutDtd As String)

    '    Dim xr As XmlReader = XmlString.GetXmlReader(xmlWithoutDtd)
    '    If xr.MoveToContent() <> XmlNodeType.Element Then
    '        Throw New ApplicationException("document element expected")
    '    End If

    '    'begin: attach dtd
    '    Dim ms As New MemoryStream()

    '    'prepend xml document element with dtd
    '    Dim xw As XmlWriter = XmlWriter.Create(ms)
    '    xw.WriteDocType(_Name, Nothing, Nothing, _Subset)
    '    xw.WriteNode(xr, False)
    '    xw.Close()

    '    ms.Position = 0
    '    'end: attach dtd

    '    Dim settings As New XmlReaderSettings()
    '    settings.ProhibitDtd = False
    '    settings.ValidationType = ValidationType.DTD
    '    Dim reader As XmlReader = XmlReader.Create(ms, settings)
    '    While reader.Read()
    '    End While

    '    reader.Close()
    '    ms.Close()
    'End Sub

    Public Function GetValidatingReader(ByVal xmlStr As String) As XmlReader

        Dim tr As New StringReader(xmlStr)
        Dim xtr As New XmlTextReader(tr)

        Return GetValidatingReader(xtr)

    End Function

    Public Function GetValidatingReader(ByVal input As Stream) As XmlReader

        Dim xtr As New XmlTextReader(input)

        Return GetValidatingReader(xtr)

    End Function

    Public Function GetValidatingReader(ByVal xtr As XmlTextReader) As XmlReader

        xtr.XmlResolver = Me
        If xtr.MoveToContent() <> XmlNodeType.Element Then
            Throw New ApplicationException("document element expected")
        End If

        'begin: attach dtd
        Dim ms As New MemoryStream()

        'prepend xml document element with dtd
        Dim xw As XmlWriter = XmlWriter.Create(ms)
        xw.WriteDocType(_Name, Nothing, Nothing, _Subset)
        xw.WriteNode(xtr, False)
        xw.Close()

        ms.Position = 0
        'end: attach dtd

        Dim settings As New XmlReaderSettings()
        settings.ProhibitDtd = False
        settings.ValidationType = ValidationType.DTD
        Dim vr As XmlReader = XmlReader.Create(ms, settings)

        Return vr

    End Function

    Public Overrides WriteOnly Property Credentials() As System.Net.ICredentials
        Set(ByVal value As System.Net.ICredentials)

        End Set
    End Property

    Public Overrides Function GetEntity(ByVal absoluteUri As System.Uri, ByVal role As String, ByVal ofObjectToReturn As System.Type) As Object

        Return New MemoryStream(_Buffer)

    End Function
End Class
